home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / program / palis.lha / Palis / src / SetMan.c < prev   
C/C++ Source or Header  |  1992-09-02  |  12KB  |  487 lines

  1. /*
  2.     ·C·O·D·E·X· ·D·E·S·I·G·N· ·S·O·F·T·W·A·R·E·
  3.     presents
  4.  
  5.     PatchLibraries Utility
  6.  
  7.     FILE:    setman.c
  8.     TASK:    (un)set my setfunction() and my _faboulus_ new function
  9.  
  10.     (c)1995 by Hans Bühler
  11. */
  12.  
  13. #include    "pl.h"
  14.  
  15. // ---------------------------
  16. // defines
  17. // ---------------------------
  18.  
  19. // for plPatch->_Cookie_
  20. #define    MAGIC_COOKIE        0x4ef9    // assembly long jump code !! * DO NOT CHANGE *
  21.  
  22. // 
  23. #define    ERR_NONE                0
  24. #define    ERR_NOLIBNODE        1            // the following are assumed to be out-of-memory-errors
  25. #define    ERR_NOOFFNODE        2            // ""
  26. #define    ERR_NOPATCHNODE    3            // ""
  27.  
  28. // offset patched by this prog
  29. #define    SETFUNC_OFF            -420        // exec/SetFunction()
  30.  
  31. // ??
  32. #define    BUFLEN                31
  33.  
  34. // ---------------------------
  35. // datatypes
  36. // ---------------------------
  37.  
  38. // ---------------------------
  39. // proto
  40. // ---------------------------
  41.  
  42. extern __asm APTR _JUMPTOOLD(register __a1 struct Library *lib, register __a0 WORD off, register __d0 APTR func, register __a2 APTR oldFunc);
  43.  
  44. static APTR ErrorOff(struct Library *userLib, WORD userOff, APTR userEntry);
  45. static struct plLib *GetLibNode(struct Library *lib);
  46. static struct plOffset *GetOffNode(struct plLib *libNode, WORD off);
  47. static struct plPatch *GetPatchNode(struct plOffset *offNode, APTR entry);
  48. static struct plLib *MakeLibNode(struct Library *lib);
  49. static struct plOffset *MakeOffNode(struct plLib *libNode, WORD off);
  50. static struct plPatch *MakePatchNode(struct plOffset *offNode, APTR patchFunc);
  51. static void RemPatches(struct plPatch *pNode);
  52.  
  53. // ---------------------------
  54. // vars
  55. // --------------------------- 
  56.  
  57. struct plBase        plBase;                    // basic structure !!!!!!!!!!
  58. static BOOL            SemAdded            =    FALSE;
  59.  
  60. static APTR            OldSetFunc        =    0;
  61.  
  62. static char            *OutOfMemPName    =    "[no memory for taskname]";
  63.  
  64. // ---------------------------
  65. // funx: manage SetFunction()
  66. // ---------------------------
  67.  
  68. /*********************************************************
  69.  * Here's what I'm talking of: my new setfunction() !!!    *
  70.  * -----------------------------------------------------    *
  71.  * NOTE: There's a little problem if I cannot allocate    *
  72.  * memory for a new patch (see below).                            *
  73.  * Up to now, in that case I just use the old SetFunc()    *
  74.  * and everything as it was before.                                *
  75.  * Additionally, an error msg is sent to the main task    *
  76.  * which will inform the user...                                    *
  77.  *********************************************************/
  78.  
  79. __asm __saveds __interrupt MySetFunction(register __a1 struct Library *userLib, register __a0 WORD userOff, register __d0 APTR userEntry)
  80. {
  81.     struct plLib        *libNode;
  82.     struct plOffset    *offNode;
  83.     struct plPatch        *patch,*next;
  84.     APTR                    retFunc;
  85.  
  86.     // -- avoid access conflicts --
  87.  
  88.     ObtainSemaphore(&plBase.Sem);
  89.  
  90.     // -- first look whether we had a patch here before... --
  91.  
  92.     offNode    =    0;
  93.     patch        =    0;
  94.  
  95.     if((libNode = GetLibNode(userLib)) &&
  96.         (offNode = GetOffNode(libNode,userOff)) &&
  97.         (patch    = GetPatchNode(offNode,userEntry)) )
  98.     {
  99.         // -- program wants to remove an old patch... --
  100.  
  101.         next    =    (struct plPatch *)patch->Node.mln_Succ;
  102.  
  103.         if(next->Node.mln_Succ)            // is there a follower ?
  104.         {
  105.             patch->PatchFunc        =    patch->OldFunc;
  106.                                                     // now, this patcher will only call
  107.                                                     // its old function
  108.             patch->OldFunc            =    0;
  109.  
  110.             retFunc    =    patch->PatchFunc;        // == patch->OldFunc (before it was cleared...)
  111.         }
  112.         else
  113.         {
  114.             retFunc    =    0;                            // use this as dummy
  115.  
  116.             for(    next = (struct plPatch *)patch->Node.mln_Pred;
  117.                     next->Node.mln_Pred;
  118.                     next = (struct plPatch *)next->Node.mln_Pred)
  119.             {
  120.                 if(retFunc = next->OldFunc)
  121.                     break;
  122.             }
  123.  
  124.             if(!retFunc)                            // -- all patches might be removed now ! --
  125.             {
  126.                 retFunc    =    _JUMPTOOLD(userLib,userOff,offNode->OriginalFunc,OldSetFunc);
  127.  
  128.                 RemPatches((struct plPatch *)next->Node.mln_Succ);        // rem all I donnot need anymore
  129.             }
  130.             else
  131.             {
  132.                 retFunc    =    _JUMPTOOLD(userLib,userOff,&next->_Cookie_,OldSetFunc);
  133.  
  134.                 RemPatches((struct plPatch *)next->Node.mln_Succ);        // here, next points to *plBase !!!
  135.             }
  136.         }
  137.     }
  138.     else
  139.     {
  140.         // -- program wants to install a new patch... --
  141.  
  142.         // -- chk if there've been errors --
  143.  
  144.         if(plBase.LowMemErr)            /* old error status... */
  145.         {
  146.             ReleaseSemaphore(&plBase.Sem);
  147.             return _JUMPTOOLD(userLib,userOff,userEntry,OldSetFunc);            // EMERGENCY EXIT
  148.         }
  149.  
  150.         // -- get new memory --
  151.  
  152.         if(!libNode)
  153.             if(!( libNode = MakeLibNode(userLib) ))
  154.             {
  155.                 return ErrorOff(userLib,userOff,userEntry);        // EMERGENCY EXIT ! (see func)
  156.             }
  157.  
  158.         if(!offNode)
  159.             if(!( offNode = MakeOffNode(libNode,userOff) ))
  160.             {
  161.                 return ErrorOff(userLib,userOff,userEntry);        // EMERGENCY EXIT ! (see func)
  162.             }
  163.  
  164.         if(!( patch = MakePatchNode(offNode,userEntry) ))
  165.         {
  166.             return ErrorOff(userLib,userOff,userEntry);        // EMERGENCY EXIT ! (see func)
  167.         }
  168.  
  169.         // -- set new function (more clearly: set my function jumping into new ;-) --
  170.  
  171.         patch->OldFunc    =    _JUMPTOOLD(userLib,userOff,&patch->_Cookie_,OldSetFunc);
  172.  
  173.         if(!offNode->OriginalFunc)
  174.             offNode->OriginalFunc    =    patch->OldFunc;                // then, it was the first !!
  175.  
  176.         retFunc    =    patch->OldFunc;
  177.     }
  178.  
  179.     // -- job done that far --
  180.  
  181.     ReleaseSemaphore(&plBase.Sem);
  182.  
  183.     return retFunc;
  184. }
  185.  
  186. /***************************************************************
  187.  * This func will be called if prog was not able to allocate    *
  188.  * memory for a new patch.                                                    *
  189.  * NOTES:    1)    A message is sent to main process to say user    *
  190.  *                    what happened                                                *
  191.  *                2)    New function is set via old SetFunction().        *
  192.  *                    Now, new patches won't be tracked !                    *
  193.  *                3)    All old patch-routines remain in memory.            *
  194.  *                    These patches might be removed savely.                *
  195.  ***************************************************************/
  196.  
  197. static APTR ErrorOff(struct Library *userLib, WORD userOff, APTR userEntry)
  198. {
  199.     plBase.LowMemErr    =    TRUE;            // ough !
  200.     ReleaseSemaphore(&plBase.Sem);
  201.  
  202.     return _JUMPTOOLD(userLib,userOff,userEntry,OldSetFunc);            // EMERGENCY EXIT
  203. }
  204.  
  205. // ---------------------------
  206. // funx: find nodes
  207. // ---------------------------
  208.  
  209. /******************
  210.  * find a libnode *
  211.  ******************/
  212.  
  213. static struct plLib *GetLibNode(struct Library *lib)
  214. {
  215.     struct plLib    *libNode;
  216.  
  217.     for(    libNode = (struct plLib *)plBase.LibList.mlh_Head;
  218.             libNode->Node.mln_Succ;
  219.             libNode = (struct plLib *)libNode->Node.mln_Succ)
  220.     {
  221.         if(lib == libNode->Lib)
  222.             return libNode;
  223.     }
  224.  
  225.     return 0;
  226. }
  227.  
  228. /******************
  229.  * find a offnode *
  230.  ******************/
  231.  
  232. static struct plOffset *GetOffNode(struct plLib *libNode, WORD off)
  233. {
  234.     struct plOffset    *offNode;
  235.  
  236.     for(    offNode = (struct plOffset *)libNode->OffList.mlh_Head;
  237.             offNode->Node.mln_Succ;
  238.             offNode = (struct plOffset *)offNode->Node.mln_Succ)
  239.     {
  240.         if(off == offNode->Offset)
  241.             return offNode;
  242.     }
  243.  
  244.     return 0;
  245. }
  246.  
  247. /****************
  248.  * find a patch *
  249.  ****************/
  250.  
  251. static struct plPatch *GetPatchNode(struct plOffset *offNode, APTR entry)
  252. {
  253.     struct plPatch    *pNode;
  254.  
  255.     for(    pNode = (struct plPatch *)offNode->PatchList.mlh_Head;
  256.             pNode->Node.mln_Succ;
  257.             pNode = (struct plPatch *)pNode->Node.mln_Succ)
  258.     {
  259.         if(pNode->OldFunc && (entry == pNode->OldFunc))
  260.             return pNode;
  261.     }
  262.  
  263.     return 0;
  264. }
  265.  
  266. // ---------------------------
  267. // funx: mk new node
  268. // ---------------------------
  269.  
  270. /*************************
  271.  * create a new lib node *
  272.  *************************/
  273.  
  274. static struct plLib *MakeLibNode(struct Library *lib)
  275. {
  276.     struct plLib    *libNode;
  277.  
  278.     if(!( libNode = AllocVec(sizeof(struct plLib), MEMF_PUBLIC|MEMF_CLEAR) ))
  279.         return 0;
  280.  
  281.     libNode->Lib    =    OpenLibrary(lib->lib_Node.ln_Name,0);
  282.                                                         // thus, it won't be expugned until we finished work !
  283.  
  284.     InitEmptyList(&libNode->OffList);
  285.     libNode->OffCnt            =    0;
  286.  
  287.     AddTail((struct List *)&plBase.LibList,(struct Node *)libNode);
  288.     plBase.LibCnt++;
  289.  
  290.     return libNode;
  291. }
  292.  
  293. /*********************
  294.  * make new off node *
  295.  *********************/
  296.  
  297. static struct plOffset *MakeOffNode(struct plLib *libNode, WORD off)
  298. {
  299.     struct plOffset    *offNode,*prec;
  300.  
  301.     if(!libNode ||
  302.         !( offNode = AllocVec(sizeof(struct plOffset), MEMF_PUBLIC|MEMF_CLEAR)) )
  303.         return 0;
  304.  
  305.     offNode->Offset            =    off;
  306.     offNode->plLib                =    libNode;
  307.  
  308.     InitEmptyList(&offNode->PatchList);
  309.     offNode->PatchCnt            =    0;
  310.  
  311.     // -- find node after which we want our new patch to be installed --
  312.  
  313.     for(    prec = (struct plOffset *)libNode->OffList.mlh_TailPred;
  314.             prec->Node.mln_Pred;
  315.             prec = (struct plOffset *)prec->Node.mln_Pred)
  316.     {
  317.         if(prec->Offset > off)
  318.             break;
  319.     }
  320.  
  321.     if(!prec->Node.mln_Pred)            // prec is minlist...
  322.         prec    =    0;                            // add head !
  323.  
  324.     Insert((struct List *)&libNode->OffList,(struct Node *)offNode,(struct Node *)prec);
  325.  
  326.     libNode->OffCnt++;
  327.  
  328.     return offNode;
  329. }
  330.  
  331. /***************************
  332.  * generate new patch node *
  333.  ***************************/
  334.  
  335. static struct plPatch *MakePatchNode(struct plOffset *offNode, APTR patchFunc)
  336. {
  337.     struct plPatch    *pNode;
  338.     struct Task        *thisTask;
  339.     char                *pName;
  340.     char                buf[BUFLEN+1];
  341.  
  342.     if(!offNode ||
  343.         !(pNode = AllocVec(sizeof(struct plPatch), MEMF_PUBLIC|MEMF_CLEAR)) )
  344.         return 0;
  345.  
  346.     pNode->_Cookie_        =    MAGIC_COOKIE;                // assembly 'jmp'
  347.     pNode->PatchFunc        =    patchFunc;
  348.     pNode->plOffset        =    offNode;
  349.  
  350.     thisTask    =    SysBase->ThisTask;
  351.     pName        =    0;
  352.  
  353.     if((thisTask->tc_Node.ln_Type == NT_PROCESS) &&
  354.         ((struct Process *)thisTask)->pr_TaskNum )
  355.     {
  356.         if(GetProgramName(buf,BUFLEN) && buf[0])
  357.             pName    =    buf;
  358.     }
  359.  
  360.     if(!pName)
  361.         pName    =    thisTask->tc_Node.ln_Name;
  362.  
  363.     if( pNode->ProcName = AllocVec(strlen(pName)+1, MEMF_PUBLIC) )
  364.         strcpy(pNode->ProcName,pName);
  365.     else
  366.         pNode->ProcName    =    OutOfMemPName;
  367.  
  368.     AddTail((struct List *)&offNode->PatchList,(struct Node *)pNode);
  369.     offNode->PatchCnt++;
  370.     plBase.PatchCnt++;
  371.  
  372.     return pNode;
  373. }
  374.  
  375. // ---------------------------
  376. // funx: remove unused nodes
  377. // ---------------------------
  378.  
  379. /*********************************************************
  380.  * remove a patch node and, if needed, all other nodes    *
  381.  *********************************************************/
  382.  
  383. static void RemPatches(struct plPatch *pNode)
  384. {
  385.     struct plPatch        *next;
  386.     struct plOffset    *offNode;
  387.     struct plLib        *plLib;
  388.  
  389.     if(!pNode)
  390.         return;
  391.  
  392.     if(plBase.LowMemErr)
  393.         return;                        /* won't be save to do that, then... */
  394.  
  395.     // -- remove all nodes not needed from plOffset --
  396.  
  397.     offNode    =    pNode->plOffset;
  398.  
  399.     while(next = (struct plPatch *)pNode->Node.mln_Succ)
  400.     {
  401.         Remove((struct Node *)pNode);
  402.         offNode->PatchCnt--;
  403.         plBase.PatchCnt--;
  404.         if(pNode->ProcName != OutOfMemPName)
  405.             FreeVec(pNode->ProcName);
  406.         FreeVec(pNode);
  407.  
  408.         pNode    =    next;
  409.     }
  410.  
  411.     // -- remove offset and check whether we need plLib anymore --
  412.  
  413.     if(!offNode->PatchCnt)
  414.     {
  415.         plLib    =    offNode->plLib;
  416.  
  417.         Remove((struct Node *)offNode);
  418.         FreeVec(offNode);
  419.  
  420.         if(!--plLib->OffCnt)
  421.         {
  422.             CloseLibrary(plLib->Lib);        // unlock library
  423.  
  424.             Remove((struct Node *)plLib);
  425.             plBase.LibCnt--;
  426.             FreeVec(plLib);
  427.         }
  428.     }
  429. }
  430.  
  431. // ---------------------------
  432. // funx: init/rem
  433. // ---------------------------
  434.  
  435. /*************************
  436.  * patch exec.library... *
  437.  *************************/
  438.  
  439. BOOL InitMyFunc(void)
  440. {
  441.     InitEmptyList(&plBase.LibList);
  442.  
  443.     plBase.Sem.ss_Link.ln_Name    =    PALIS_SEMAPHORE_NAME;
  444.     plBase.Sem.ss_Link.ln_Pri    =    0;
  445.  
  446.     plBase.LibCnt        =    0;
  447.     plBase.PatchCnt    =    0;
  448.     plBase.LowMemErr    =    FALSE;
  449.     plBase.Version        =    PALIS_VERSION;
  450.  
  451.     AddSemaphore(&plBase.Sem);
  452.     SemAdded        =    TRUE;
  453.  
  454.     OldSetFunc    =    SetFunction((struct Library *)SysBase,SETFUNC_OFF,(APTR)MySetFunction);
  455. }
  456.  
  457. /************************************************************
  458.  * unpatch exec.                                                            *
  459.  * I assume that SetFunction() is _not_ been patched since    *
  460.  * quitting this prog will only work if no more patches        *
  461.  * (that is to say patches to SetFunction(), too) are known.*
  462.  * I may change some things here in future... ;=(                *
  463.  ************************************************************/
  464.  
  465. void RemMyFunc(void)
  466. {
  467.     // -- remove old function --
  468.  
  469.     if(OldSetFunc)
  470.     {
  471.         _JUMPTOOLD((struct Library *)SysBase,SETFUNC_OFF,OldSetFunc,OldSetFunc);
  472.  
  473.         Delay(2);            // wait till any task left my SetFunc()
  474.                                 // (new calls will go for the old SetFunction..,
  475.                                 // current calls will at any time use ObtainSemaphore()
  476.         ObtainSemaphore(&plBase.Sem);
  477.     }
  478.  
  479.     if(SemAdded)
  480.         RemSemaphore(&plBase.Sem);
  481.  
  482.     /*
  483.         aufräumen ist nicht, da die evtl. noch vorhanden patches u.U.
  484.         noch angesprungen werden... ;/(
  485.     */
  486. }
  487.